#include "game.h"
#include "server.h"
#include "tower.h"
#include "unit.h"
#include <QColor>
#include <QDebug>
#include <QVector3D>
#include <QDomDocument>
#include <QDomNodeList>
#include <QDomElement>
#include <QFile>
#include <QStringList>

//Game* Game::gInstance = NULL;
/*
Game* Game::instance()
{
   if (gInstance == NULL)
   {
      gInstance = new Game();
      qDebug() << "Game created!";
   }
   return gInstance;
}
*/

Game::Game()
{
   entityManager.setGame(this);
}


Game::~Game()
{
   qDebug() << "~Game";
}


/*
Entity::EntityListType Entity::addEntitySquad(const quint32 playerID, const quint32 squadID, const EntityBaseStats &stats, quint32 squadSize, QPointF &pos);
{
   Entity::EntityListType list = entityManager.addEntitySquad(playerID, squadID, stats, squadSize);
   QPointF newPos(pos);
   foreach (Entity *e, list)
   {
      e->setPosition(newPos);
      newPos.setX(newPos.x()+stats.size*2.5+15);

      switch (stats.type)
      {
      case ENTITY_UNIT:
      {
         Unit *u = dynamic_cast<Unit*>(e);
         u->path = path(); // FIXME, path here not correct anymore
      }
      break;
      case ENTITY_TOWER:
      {
         //
      }
      default:
      break;
      }
   }
   return list;
}
*/

Entity* Game::addEntity(const quint32 playerID, const EntityBaseStats &stats, QPointF &pos)
{
   Entity *entity = entityManager.addEntity(playerID, stats);
   entity->setPosition(pos);
   entity->onAddToGame();
   return entity;
}


bool Game::addEntity(Entity *entity)
{
   bool ret=false;
   if (entity)
   {
      ret = entityManager.addEntity(entity);
      entity->onAddToGame();
   }
   return ret;
}


void Game::tick(qreal timeDelta)
{
   //qDebug() << "Game::tick";

   //qDebug() << "Game::timeDelta" << timeDelta;
   entityManager.tick(timeDelta);
}


void Game::setCurrentMap(const QString &filename)
{
   mCurrentMap = filename;
   parseMapFile(mCurrentMap);
}


QString Game::currentMap()
{
   return mCurrentMap;
}


void Game::parseMapFile(const QString &filename)
{
   QDomDocument doc("Map");
   QFile file(filename);
   if(!file.open(QIODevice::ReadOnly))
   {
     qDebug() << "XML: ERROR could not open map XML>" << filename;
     return;
   }
   if(!doc.setContent(&file))
   {
     qDebug() << "XML: ERROR could not read map XML (malformed?)>" << filename;
     file.close();
     return;
   }
   file.close();

   QDomNodeList nodes = doc.elementsByTagName("Path");
   for (int i=0; i<nodes.size(); ++i)
   {
      PathType path;
      QString pathName = nodes.at(i).toElement().attribute("name");

      QDomElement elem = nodes.at(i).firstChildElement("PointList");
      QStringList strList(elem.text().split(","));
      for (int j=0; j<strList.size(); ++j)
      {
         QString str = strList.at(j).simplified();
         QStringList strList2(str.split(" "));
         // Assuming tag values are paired correctly...
         path.append(QPoint(strList2.at(0).toInt(), strList2.at(1).toInt()));
      }
      //qDebug() << "Game::parseMapFile: path=" << pathName;
      mPaths.insert(pathName, path);
   }

   nodes = doc.elementsByTagName("UnitEmitter");
   for (int i=0; i<nodes.size(); ++i)
   {
      UnitEmitter *emitter = new UnitEmitter(0);

      // Create UnitEmitter entity...
      QDomElement elem = nodes.at(i).firstChildElement("Position");
      QStringList strList(elem.text().simplified().split(" "));
      emitter->setPosition(QPointF(strList.at(0).simplified().toDouble(), strList.at(1).simplified().toDouble()));

      elem = nodes.at(i).firstChildElement("EmitPosition");
      strList = (elem.text().simplified().split(" "));
      emitter->setEmitPosition(QPointF(strList.at(0).simplified().toDouble(), strList.at(1).simplified().toDouble()));

      elem = nodes.at(i).firstChildElement("Rotation");
      emitter->setRotation(elem.text().toDouble());

      elem = nodes.at(i).firstChildElement("Capacity");
      emitter->setCapacity(elem.text().toInt());

      elem = nodes.at(i).firstChildElement("Rate");
      emitter->setRate(elem.text().toDouble());

      elem = nodes.at(i).firstChildElement("Follows");
      emitter->setPathName(elem.text());

      qDebug() << "Game::parseMapFile: UnitEmitter=" << emitter->position() << "rot=" << emitter->rotation() << "cap=" << emitter->capacity();

      addEntity(emitter);
   }
}


PathType Game::path()
{
   PathType ret;
   if (!mPaths.isEmpty())
      return mPaths.begin().value();
   return ret;
}


PathType Game::path(const QString &pathname)
{
   PathType ret;
   if (!mPaths.isEmpty())
      return mPaths.value(pathname);
   return ret;
}


void Game::removeInactiveEntities()
{
   entityManager.removeInactiveEntities();
}


QTime Game::currentTime()
{
   return (server) ? server->currentTime() : QTime::currentTime();
}


void Game::entityDoDamage(Entity *attacker, Entity *target, const qint32 amount)
{
   // Do any damage mitigation/modification from target here
   QColor aColor(attacker->color());
   QColor tColor(target->color());

   qreal rDmg(1.0/3.0*(255 - abs(aColor.red()-tColor.red()))),
         gDmg(1.0/3.0*(255 - abs(aColor.green()-tColor.green()))),
         bDmg(1.0/3.0*(255 - abs(aColor.blue()-tColor.blue())));

   //qDebug() << aColor << ", " << tColor;
   //qDebug() <<  QVector3D(rDmg, gDmg, bDmg);

   qint32 damage(amount * ((rDmg + gDmg + bDmg)/255));

   //qDebug() << "Game::entityDoDamage=" << damage;

   target->setHealth(target->health()-damage);
   server->sendEntityAttack(attacker->id(), target->id(), damage);


   // Killed target?
   if (target->health() <= 0)
   {
      attacker->setTarget(0);
      target->setActive(false);
   }
}

/*
void Game::postEvent(Event *event)
{
   mEvents.append(event);
}

EventListType& Game::events()
{
   return mEvents;
}
*/
